function getFirstScreenTime() {
  const details = [];
  return new Promise(function (resolve, reject) {
    // 5s之内先收集所有的dom变化，并以key（时间戳）、value（dom list）的结构存起来。

    const observeDom = observeDoc(details);

    setTimeout(function () {
      observeDom.disconnect();
      console.log('details', details);
      resolve(details);
    }, 5000);
  }).then(function (details) {
    return compareTime(details);
  });
}

// 监听文档
function observeDoc(details) {
  var observeDom = new MutationObserver(function (mutations) {
    if (!mutations || !mutations.forEach) return;
    var detail = {
      time: performance.now(),
      roots: [],
      imgs: [],
    };

    mutations.forEach(function (mutation) {
      if (!mutation || !mutation.addedNodes || !mutation.addedNodes.forEach) {
        return;
      }
      mutation.addedNodes.forEach(function (ele) {
        const nodeName = ele.nodeName.toLocaleLowerCase();
        const isImg = nodeName === 'img';
        const isValidEle = isEleValid(ele, detail.roots);
        if (isValidEle) {
          detail.roots.push(ele);
          if (isImg) {
            detail.imgs.push(ele);
          }
        }
      });
    });
    if (detail.roots.length) {
      details.push(detail);
    }
  });
  observeDom.observe(document, {
    childList: true,
    subtree: true,
  });
  return observeDom;
}

// 比较首屏内DOM时间
function compareTime(details) {
  // 分析上面收集到的数据，返回最终的结果
  const domRenderTime = [];
  const allImgs = [];
  const allImgLoadTimes = [];

  details.forEach(function (detail) {
    // 拿到所有首屏DOM 的 渲染时间
    for (var i = 0; i < detail.roots.length; i++) {
      const ele = detail.roots[i];
      if (isInFSAndVisible(ele)) {
        domRenderTime.push(detail.time);
        // 同一个 detail 的 节点，时间一样，不用继续收集了
        break;
      }
    }

    // 拿到所有首屏中的图片
    for (var i = 0; i < detail.imgs.length; i++) {
      const ele = detail.imgs[i];
      if (isInFSAndVisible(ele)) {
        allImgs.push(ele.src);
      }
    }
  });

  // 遍历当前请求的图片中，如果有开始请求时间在首屏dom渲染期间的，则表明该图片是首屏渲染中的一部分，
  // 所以dom渲染时间和图片返回时间中大的为首屏渲染时间
  window.performance.getEntriesByType('resource').forEach(function (resource) {
    const url = resource.name;
    if (resource.initiatorType === 'img' && allImgs.indexOf(url) > -1) {
      allImgLoadTimes.push(resource.responseEnd);
    }
  });

  console.log('allImgs', allImgs);
  console.log('domRenderTime', domRenderTime);
  console.log('allImgLoadTimes', allImgLoadTimes);

  const resultTime = Math.max(...domRenderTime, ...allImgLoadTimes);

  return resultTime;
}

// 节点是否有效
function isEleValid(ele, arr) {
  const ignoreEleList = ['script', 'style', 'link', 'br'];
  const nodeName = ele.nodeName.toLocaleLowerCase();
  const isEleNode = ele.nodeType === 1;
  const isRenderNode = ignoreEleList.indexOf(nodeName) !== -1;
  if (isEleNode && isRenderNode) {
    if (isInFS(ele)) {
      if (!isElderOrExitEle(ele, arr)) {
        return true;
      }
    }
  }
  return false;
}

// dom 是否有效，过滤
function isEleValid(ele, arr) {
  const ignoreEleList = ['script', 'style', 'link', 'br'];
  const nodeName = ele.nodeName.toLocaleLowerCase();
  const isEleNode = ele.nodeType === 1;
  const isRenderNode = ignoreEleList.indexOf(nodeName) === -1;
  if (isEleNode && isRenderNode) {
    if (isInFS(ele)) {
      if (!isElderOrExitEle(ele, arr)) {
        return true;
      }
      // 图片另算
      else if (nodeName === 'img') {
        return true;
      }
    }
  }
  return false;
}

// 是否已经存在节点，或者是长辈节点
function isElderOrExitEle(target, arr) {
  if (!target || target === document.documentElement) {
    return false;

    // 说明数组已经存在这个节点
  } else if (arr.indexOf(target) !== -1) {
    return true;

    // 不要长辈节点
  } else {
    return isElderOrExitEle(target.parentElement, arr);
  }
}

// 位置是否首屏中
function isInFS(target) {
  if (!target || !target.getBoundingClientRect) return false;
  var rect = target.getBoundingClientRect(),
    screenHeight = window.innerHeight,
    screenWidth = window.innerWidth;
  return (
    rect.left >= 0 &&
    rect.left < screenWidth &&
    rect.top >= 0 &&
    rect.top < screenHeight
  );
}

// 首屏中，并且可见
function isInFSAndVisible(target) {
  if (!target || !target.getBoundingClientRect) return false;
  var rect = target.getBoundingClientRect();
  const isvisible = isVisible(target);
  const hasArea = rect.width > 0 && rect.height > 0;

  return isInFS(target) && hasArea && isvisible;
}

// 是否可见
function isVisible(target) {
  target.style.opacity = 'inherit';
  var rawOpacity = getStyle(target, 'opacity');
  var visibility = getStyle(target, 'visibility');

  var opacity = +rawOpacity;
  if (opacity != rawOpacity) {
    opacity = 1; // can not check old browser
  }
  if (opacity > 0.09 || visibility === 'visible') {
    return true;
  }
  return false;
}

// 获取样式
function getStyle(el, name) {
  if (window.getComputedStyle) {
    return getComputedStyle(el, null)[name];
  }
  if (el.currentStyle) {
    return el.currentStyle[name];
  }
}
